package net.csdn.business.common.utils;

import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author likun
 * @date 2022/6/20 17:36
 */
public class TokenUtil {
    private static final String COMMA = ",";

    private static final Long DIFF_TIME = 60 * 1000L;

    private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();

    private static final String DATE_FORMAT = "yyyyMMddHHmm";

    /**
     * 生成系统服务调用鉴权token
     *
     * @param ak ak
     * @param sk sk
     * @return String
     */
    public static String generateToken(String ak, String sk) {
        // try {
        //     Date timestamp = new Date();
        //     return sha256(ak + COMMA + sk + new SimpleDateFormat(DATE_FORMAT).format(timestamp));
        // } catch (UnsupportedEncodingException e) {
        //     return null;
        // }
        return generateToken(ak, sk, new Date());
    }

    /**
     * 生成token
     *
     * @param ak   ak
     * @param sk   sk
     * @param date 时间
     * @return String
     */
    public static String generateToken(String ak, String sk, Date date) {
        try {
            return sha256(ak + COMMA + sk + new SimpleDateFormat(DATE_FORMAT).format(date));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 验证token
     *
     * @param ak    ak
     * @param sk    sk
     * @param token 待验证token
     * @return Boolean
     */
    public static boolean verifyToken(String ak, String sk, String token) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        Date date = new Date();
        if (token.equals(generateToken(ak, sk, date))) {
            return true;
        }
        // fix 时间偏移导致的验证错误
        if (token.equals(generateToken(ak, sk, new Date(date.getTime() - DIFF_TIME)))) {
            return true;
        }
        return token.equals(generateToken(ak, sk, new Date(date.getTime() + DIFF_TIME)));
    }

    /**
     * sha1
     *
     * @param code 待加密code
     * @return String
     */
    private static String sha256(@NonNull String code) throws UnsupportedEncodingException {
        MessageDigest sha;
        try {
            sha = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        sha.update(code.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(sha.digest());
    }

    /**
     * 转换字节为16进制字符串
     *
     * @param bytes 字节数组
     * @return String
     */
    private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

}